﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

namespace ibba.src.norisk.Utils
{
    public class Serializator
    {
        /// <summary>
        /// Tempo de duração das instancias em memória. O tempo é definido em minutos.
        /// </summary>

        #region Método GetSerializerFor() - gerenciamento das instâncias de XmlSerializer
        private static Dictionary<string, XmlSerializer> _serializers = new Dictionary<string, XmlSerializer>();
        private static object _syncObject = new object();



        private XmlSerializer GetSerializerFor(Type type_, Type[] extraTypes_)
        {
            string _key = type_.GetHashCode().ToString();
            if (extraTypes_ != null)
            {
                foreach (Type type in extraTypes_)
                    _key += "_" + type.GetHashCode();
            }

            if (_serializers == null)
                _serializers = new Dictionary<string, XmlSerializer>();

            while (!_serializers.ContainsKey(_key))
                _serializers.Add(_key, (extraTypes_ == null ? new XmlSerializer(type_) : new XmlSerializer(type_, extraTypes_)));

            return _serializers[_key];
        }

        #endregion

        public string Serialize(object instance)
        {
            return Serialize(instance, null);
        }

        public string Serialize(object instance, Type[] extraTypes)
        {
            XmlWriterSettings _xmlWriterSettings = new XmlWriterSettings();
            XmlSerializer _serializer = GetSerializerFor(instance.GetType(), extraTypes);
            XmlSerializerNamespaces _xmlnsEmpty = new XmlSerializerNamespaces();
            string _xmlContent = "";

            try
            {
                _xmlWriterSettings.NewLineChars = "";
                _xmlWriterSettings.NewLineHandling = NewLineHandling.None;
                _xmlWriterSettings.NewLineOnAttributes = false;
                _xmlWriterSettings.OmitXmlDeclaration = true;
                //_xmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
                _xmlWriterSettings.Indent = false;

                _xmlnsEmpty.Add("", "");

                using (MemoryStream _stream = new MemoryStream())
                {
                    using (XmlWriter _xmlWriter = XmlWriter.Create(_stream, _xmlWriterSettings))
                    {
                        _serializer.Serialize(_xmlWriter, instance, _xmlnsEmpty);

                        _xmlWriter.Flush();
                    }

                    _stream.Position = 0;

                    using (StreamReader _streamReader = new StreamReader(_stream))
                    {
                        _xmlContent = _streamReader.ReadToEnd();
                    }
                }

                return _xmlContent;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                _xmlContent = null;
                _xmlWriterSettings = null;
                _serializer = null;
                _xmlnsEmpty = null;
            }
        }

        public object Deserialize(string xmlContent_, Type baseType_, Type[] extraTypes)
        {
            XmlSerializer _serializer = null;
            object _deserializedObject = null;

            try
            {
                if (string.IsNullOrEmpty(xmlContent_))
                    return Activator.CreateInstance(baseType_);

                _serializer = GetSerializerFor(baseType_, extraTypes);

                using (StringReader _stringReader = new StringReader(xmlContent_))
                {
                    _deserializedObject = _serializer.Deserialize(_stringReader);
                }

                return _deserializedObject;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                xmlContent_ = null;
                _deserializedObject = null;
                _serializer = null;
            }
        }

        public T Deserialize<T>(string xmlContent)
        {
            return Deserialize<T>(xmlContent, null);
        }

        public T Deserialize<T>(string xmlContent, Type[] extraTypes)
        {
            return (T)Deserialize(xmlContent, typeof(T), extraTypes);
        }
    }
}